/*----------------------------------------------------------------------------
 * Copyright (c) Huawei Technologies Co., Ltd. 2013-2019. All rights reserved.
 * Description: Mpu
 * Author: zhangfanfan
 * Create: 2013-01-01
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific prior written
 * permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *---------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
 * Notice of Export Control Law
 * ===============================================
 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
 * applicable export control laws and regulations.
 *---------------------------------------------------------------------------*/

/**@defgroup los_mpu Mpu
 * @ingroup kernel
 */

#ifndef _LOS_MPU_H
#define _LOS_MPU_H

#include "los_base.h"
#include "los_sys.h"
#include "los_task.h"

#ifdef __cplusplus
#if __cplusplus
 extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */

#define MPU_DISABLE                            0             // disable mpu
#define MPU_ENABLE                             0x7           // enable mpu

/**
 * @ingroup los_mpu
   * MPU support number : MPU maximum number of region support(According to the cotex-m4 authority Guide)
 */
#define MPU_MAX_SUPPORT                        8             // MPU maximum support number

/**
 * @ingroup los_mpu
   * RAM address range : Need to be filled in before setting the protected area
   * Can refer to the RAM address range in the icf file
 */
#define MPU_MIN_RAM_ADDRESS                   0x20000400    // Minimum RAM address
#define MPU_MAX_RAM_ADDRESS                   0x2001FFFF    // Maximum RAM address

/**
 * @ingroup los_mpu
 * Region size.
 */
#define MPU_REGION_SIZE_32B                    (0x04)
#define MPU_REGION_SIZE_64B                    (0x05)
#define MPU_REGION_SIZE_128B                   (0x06)
#define MPU_REGION_SIZE_256B                   (0x07)
#define MPU_REGION_SIZE_512B                   (0x08)
#define MPU_REGION_SIZE_1KB                    (0x09)
#define MPU_REGION_SIZE_2KB                    (0x0A)
#define MPU_REGION_SIZE_4KB                    (0x0B)
#define MPU_REGION_SIZE_8KB                    (0x0C)
#define MPU_REGION_SIZE_16KB                   (0x0D)
#define MPU_REGION_SIZE_32KB                   (0x0E)
#define MPU_REGION_SIZE_64KB                   (0x0F)
#define MPU_REGION_SIZE_128KB                  (0x10)
#define MPU_REGION_SIZE_256KB                  (0x11)
#define MPU_REGION_SIZE_512KB                  (0x12)
#define MPU_REGION_SIZE_1MB                    (0x13)
#define MPU_REGION_SIZE_2MB                    (0x14)
#define MPU_REGION_SIZE_4MB                    (0x15)
#define MPU_REGION_SIZE_8MB                    (0x16
#define MPU_REGION_SIZE_16MB                   (0x17)
#define MPU_REGION_SIZE_32MB                   (0x18)
#define MPU_REGION_SIZE_64MB                   (0x19)
#define MPU_REGION_SIZE_128MB                  (0x1A)
#define MPU_REGION_SIZE_256MB                  (0x1B)
#define MPU_REGION_SIZE_512MB                  (0x1C)
#define MPU_REGION_SIZE_1GB                    (0x1D)
#define MPU_REGION_SIZE_2GB                    (0x1E)
#define MPU_REGION_SIZE_4GB                    (0x1F)

/**
 * @ingroup los_mpu
 * Access permission.
 */
#define MPU_DEFS_RASR_AP_NO_ACCESS             (0)  // privilege level and user level are prohibited
#define MPU_DEFS_RASR_AP_PRIV_RW               (1)  // only privilege level can be read and write
#define MPU_DEFS_RASR_AP_PRIV_RW_USER_RO       (2)  // privilege level read and write, user level read only
#define MPU_DEFS_RASR_AP_FULL_ACCESS           (3)  // privilege level and user level can be read and write
#define MPU_DEFS_RASR_AP_PRIV_RO               (5)  // privilege level read only, user level is prohibited
#define MPU_DEFS_RASR_AP_RO                    (6)  // privilege level and user level read only

/**
 * @ingroup los_mpu
 * region info
 * uwBaseAddress must be in the range of RAM
 * uwAccessPermission and uwRegionSize are not arbitrary input, selected by the definition of the macro
 */
typedef struct tagRegionInfo {
    UINT8  ucNumber;               // number of MPU register to be checked
    UINT32 uwBaseAddress;          // set the base address of the protected region, the base address must be in the range of RAM
    UINT32 uwAccessPermission;     // privilege level and user level access permission
    BOOL   bSharable;              // whether to share
    BOOL   bCachable;              // whether cache
    BOOL   bBuffable;              // whether buffer
    UINT32 uwRegionSize;           // region size
    BOOL   bHfnmiena;              // Whether in the NMI and hard fault service routine is not mandatory in addition to MPU
    BOOL   bXN;                    // To indicate whether instructions are fetchable in this region, 0 fetchable; 1: otherwise
}MPU_REGION_INFO;

/**
* @ingroup los_cpup
* MPU error code: The pointer to an input parameter is NULL.
*
* Value: 0x02001200
*
* Solution: Check whether the pointer to the input parameter is usable.
*/
#define LOS_ERRNO_MPU_PTR_NULL                    LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x00)

/**
* @ingroup los_mpu
* MPU error code: The base address is not aligned to the boundary of the region capacity.
*
* Value: 0x02001201
*
* Solution: Check base address.
*/
#define LOS_ERRNO_MPU_INVALID_BASE_ADDRESS        LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x01)

/**
* @ingroup los_mpu
* MPU error code: Capacity less than 32 bytes.
*
* Value: 0x02001202
*
* Solution: Guaranteed that the capacity is greater than or equal to 32 bytes.
*/
#define LOS_ERRNO_MPU_INVALID_CAPACITY            LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x02)

/**
* @ingroup los_mpu
* MPU error code: Chip is not configured MPU.
*
* Value: 0x02001203
*
* Solution: Make sure the chip is configured with MPU.
*/
#define LOS_ERRNO_MPU_NOT_CONFIGURED              LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x03)

/**
* @ingroup los_mpu
* MPU error code: Invalid number.
*
* Value: 0x02001204
*
* Solution: Enter a valid number.
*/
#define LOS_ERRNO_MPU_INVALID_NUMBER              LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x04)

/**
* @ingroup los_cpup
* MPU error code: Region has already been enabled.
*
* Value: 0x02001205
*
* Solution: If you want to re enable the region, please first in addition to the region.
*/
#define LOS_ERRNO_MPU_REGION_IS_ENABLED           LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x05)

/**
* @ingroup los_cpup
* MPU error code: Region has already been disabled.
*
* Value: 0x02001206
*
* Solution: If you want to re enable the region, please first in addition to the region.
*/
#define LOS_ERRNO_MPU_REGION_IS_DISABLED          LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x06)

/**
* @ingroup los_cpup
* MPU error code: Invalid access.
*
* Value: 0x02001207
*
* Solution: Checking whether the access is correct.
*/
#define LOS_ERRNO_MPU_REGION_INVALID_ACCESS       LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x07)

/**
* @ingroup los_cpup
* MPU error code: Base address is not in RAM.
*
* Value: 0x02001208
*
* Solution: Checking base address
*/
#define LOS_ERRNO_MPU_BASE_ADDRESS_NOT_IN_RAM     LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x08)

/**
* @ingroup los_cpup
* MPU error code: According to the current base address, the size of the application is too big.
*
* Value: 0x02001209
*
* Solution: baseAddress + regionSize must not exceed RAM Max address
*/
#define LOS_ERRNO_MPU_REGION_SIZE_IS_TOO_BIG      LOS_ERRNO_OS_ERROR(LOS_MOD_MPU, 0x09)

/**
 *@ingroup los_mpu
 *@brief Obtain the set protection region.
 *
 *@par Description:
 *This API is used to set protection region.
 *@attention
 *<ul>
 *<li>the base address must be in the range of RAM.</li>
 *</ul>
 *
 *@param  pstMpuInfo     [IN] MPU_REGION_INFO. Set the related configuration information for the protected area
 *
 *@retval #LOS_ERRNO_MPU_TASK_PTR_NULL          0x02001200: The pointer to an input parameter is NULL.
 *@retval #LOS_ERRNO_MPU_INVALID_BASE_ADDRESS   0x02001201: The base address is not aligned to the boundary of the region capacity.
 *@retval #LOS_ERRNO_MPU_INVALID_CAPACITY       0x02001202: Capacity less than 32 bytes.
 *@retval #LOS_ERRNO_MPU_NOT_CONFIGURED         0x02001203: Chip is not configured MPU.
 *@retval #LOS_ERRNO_MPU_INVALID_NUMBER         0x02001204: Invalid number.
 *@retval #LOS_ERRNO_MPU_REGION_IS_ENABLED      0x02001205: Region has already been enabled.
 *@retval #LOS_ERRNO_MPU_REGION_IS_DISABLED     0x02001206: Region has already been disabled.
 *@par Dependency:
 *<ul><li>los_mpu.h: the header file that contains the API declaration.</li></ul>
 *@since Huawei LiteOS V100R001C00
 */
extern UINT32 LOS_SetProtectionRegion (MPU_REGION_INFO  *pstMpuInfo);

/**
 *@ingroup los_mpu
 *@brief Obtain the set protection region.
 *
 *@par Description:
 *This API is used to set protection region.
 *@attention
 *<ul>
 *<li>.</li>
 *</ul>
 *
 *@param  ucNumber     [IN] UINT8.which region to be selected.
 *
 *@retval #LOS_ERRNO_MPU_INVALID_NUMBER         0x02001204: Invalid number.
 *@retval #LOS_ERRNO_MPU_REGION_IS_DISABLED     0x02001206: Region has already been disabled.
 *@par Dependency:
 *<ul><li>los_mpu.h: the header file that contains the API declaration.</li></ul>
 *@since Huawei LiteOS V100R001C00
 */
extern UINT32 LOS_RegionDisable(UINT8 ucNumber);

#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

#endif /* _LOS_MPU_H */

